package cn.hackcloud.demo.dubbo;

import cn.hackcloud.demo.dubbo.rpc.IUserService;
import com.alibaba.dubbo.remoting.exchange.ResponseCallback;
import com.alibaba.dubbo.rpc.protocol.dubbo.FutureAdapter;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.beanutil.JavaBeanDescriptor;
import org.apache.dubbo.common.beanutil.JavaBeanSerializeUtil;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.io.UnsafeByteArrayInputStream;
import org.apache.dubbo.common.io.UnsafeByteArrayOutputStream;
import org.apache.dubbo.common.serialize.Serialization;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.registry.Registry;
import org.apache.dubbo.registry.RegistryFactory;
import org.apache.dubbo.rpc.Constants;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.service.GenericService;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * 提供的异步调用
 */
public class ApiAsyncConsumer extends BasConsumer {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        async();
    }
    /**
     * 2.6
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public static void async() throws ExecutionException, InterruptedException {
        ReferenceConfig<IUserService> reference = referenceConfig();
        //设置为异步
        reference.setAsync(true);
        IUserService userService = reference.get();

        System.out.println(userService.sync("1"));
        RpcContext.getContext().setAttachment("bizNo","66666");
        Future future = RpcContext.getContext().getFuture();
        print(future.get());
    }

    /**
     * 2.6异步回调
     */
    public static void asyncCallBack() {
        ReferenceConfig<IUserService> reference = referenceConfig();
        //设置为异步
        reference.setAsync(true);
        IUserService userService = reference.get();
        System.out.println(userService.sync("1"));
        FutureAdapter adapter = (FutureAdapter) RpcContext.getContext().getFuture();
        adapter.getFuture().setCallback(new ResponseCallback() {
            @Override
            public void done(Object response) {
                print(response);
            }

            @Override
            public void caught(Throwable exception) {

            }
        });
    }

    /**
     * 2.7异步回调
     */
    public static void asyncCallBackNew() {
        ReferenceConfig<IUserService> reference = referenceConfig();
        //设置为异步
        reference.setAsync(true);
        IUserService userService = reference.get();
        userService.async2("1").whenComplete((v, t) -> {
            print(v);
        });
    }

    /**
     * 泛化调用 true
     */
    public static void generic() {
        ReferenceConfig<GenericService> reference = referenceConfig();
        reference.setGeneric(true);
        GenericService userService = reference.get();
        Map<String, Object> map = new HashMap<>(2);
        map.put("userId", "1");
        Object o = userService.$invoke("sync", new String[]{"java.lang.String"}, new Object[]{"1"});
        print(o);
    }

    /**
     * 泛化调用 bean
     */
    public static void genericBean() {
        ReferenceConfig<GenericService> reference = referenceConfig();
        reference.setGeneric("bean");
        GenericService userService = reference.get();
        JavaBeanDescriptor param = JavaBeanSerializeUtil.serialize("1");
        Object o = userService.$invoke("sync", new String[]{"java.lang.String"}, new Object[]{param});
        print(JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor) o));
    }

    /**
     * 泛化调用 nativeJava
     */
    public static void genericNativeJava() throws IOException, ClassNotFoundException {
        ReferenceConfig<GenericService> reference = referenceConfig();
        reference.setGeneric("nativejava");
        GenericService userService = reference.get();
        UnsafeByteArrayOutputStream os = new UnsafeByteArrayOutputStream();
        //序列化为二进制数据
        ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(Constants.GENERIC_SERIALIZATION_NATIVE_JAVA)
                .serialize(null, os)
                .writeObject("1");
        Object o = userService.$invoke("sync", new String[]{"java.lang.String"}, new Object[]{os.toByteArray()});
        UnsafeByteArrayInputStream in = new UnsafeByteArrayInputStream((byte[]) o);
        Object o1 = ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(Constants.GENERIC_SERIALIZATION_NATIVE_JAVA)
                .deserialize(null, in).readObject();
        print(o1);
    }

    /**
     * dubbo mock调用
     */
    public static void mock() {
        ReferenceConfig<IUserService> reference = referenceConfig();
        //设置启动时不检查服务提供者是否可用
        reference.setCheck(false);
        //设置mock调用
        reference.setMock("true");
        IUserService userService = reference.get();
        print(userService.sync("1"));
    }

    public void ll() {
        RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
        Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
        registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null"));
    }
}
